article.txt

WordPress Docker 部署 HTTPS 全流程笔记

背景

在阿里云 ECS 上通过 Docker Compose 部署 WordPress,初始只有 HTTP(80端口),需要升级到 HTTPS(443端口),并实现 SSL 证书自动续期。


一、核心架构

1
2
3
用户 → 阿里云安全组(80/443) → Nginx(反向代理) → WordPress(FPM) → MariaDB

acme.sh(自动续期)

二、完整配置

2.1 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
services:
wordpress:
image: wordpress:7.0.1-php8.3-fpm-alpine
container_name: wp-course
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wpstrongpassword
WORDPRESS_DB_NAME: wordpress
volumes:
- ./html:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
depends_on:
- db

db:
image: mariadb:11.8
container_name: wp-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wpstrongpassword
volumes:
- ./db_data:/var/lib/mysql

nginx:
image: nginx:alpine
container_name: wp-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./html:/var/www/html
- ./cert:/etc/nginx/cert:ro
depends_on:
- wordpress

acme:
image: neilpang/acme.sh:latest
container_name: wp-acme
restart: unless-stopped
entrypoint: ["/entrypoint.sh"]
command: daemon
environment:
- Ali_Key=你的阿里云AccessKey
- Ali_Secret=你的阿里云AccessSecret
- LE_WORKING_DIR=/acme.sh
volumes:
- ./acme_data:/acme.sh
- ./cert:/acme.sh/certs_out
- ./entrypoint.sh:/entrypoint.sh:ro
- /root/reload_nginx.sh:/root/reload_nginx.sh:ro
- /var/run/docker.sock:/var/run/docker.sock:ro

2.2 nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
server {
listen 80 default_server;
server_name vid.szzhuoju.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl default_server;
server_name vid.szzhuoju.com;

root /var/www/html;
index index.php;

client_max_body_size 2048M;

ssl_certificate /etc/nginx/cert/vid.szzhuoju.com.pem;
ssl_certificate_key /etc/nginx/cert/vid.szzhuoju.com.key;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}

location ~ /\. {
deny all;
}
}

2.3 entrypoint.sh(解决 acme 容器内 docker-cli 缺失问题)

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh

# 如果没装 docker-cli,就装(换国内源,抗墙)
if ! command -v docker > /dev/null 2>&1; then
echo "Installing docker-cli..."
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk add --no-cache docker-cli
fi

# 把控制权交还给镜像自带的入口
exec /entry.sh "$@"

2.4 reload_nginx.sh(续期后重载 Nginx)

1
2
#!/bin/bash
docker exec wp-nginx nginx -s reload

三、部署步骤

3.1 初始化

1
2
3
4
5
6
7
8
9
10
11
12
# 创建目录结构
mkdir -p ~/wordpress/{html,cert,acme_data,db_data}
cd ~/wordpress

# 创建上述所有配置文件
# docker-compose.yml
# nginx.conf
# entrypoint.sh
# reload_nginx.sh

# 给脚本执行权限
chmod +x entrypoint.sh /root/reload_nginx.sh

3.2 启动服务

1
docker compose up -d

3.3 申请 SSL 证书

1
2
3
4
5
6
7
8
9
10
11
12
# 设置默认 CA 为 Let's Encrypt(国内网络友好)
docker exec wp-acme acme.sh --set-default-ca --server letsencrypt

# 注册账号
docker exec wp-acme acme.sh --register-account -m [email protected]

# 申请证书(DNS验证,阿里云API)
docker exec wp-acme acme.sh --issue --dns dns_ali \
-d szzhuoju.com \
--dnssleep 300 \
--server letsencrypt \
--force

3.4 安装证书到 Nginx

1
2
3
4
docker exec wp-acme acme.sh --install-cert -d szzhuoju.com \
--key-file /acme.sh/certs_out/szzhuoju.com.key \
--fullchain-file /acme.sh/certs_out/szzhuoju.com.pem \
--reloadcmd "sh /root/reload_nginx.sh"

3.5 验证

1
2
3
4
5
# 检查 HTTPS 是否正常
curl -I https://szzhuoju.com

# 检查证书信息
docker exec wp-acme openssl x509 -enddate -noout -in /acme.sh/certs_out/szzhuoju.com.pem

四、踩坑记录

坑1:acme.sh 默认 CA 在国内网络不稳定

  • 现象:申请证书时卡在 Pending
  • 解决--set-default-ca --server letsencrypt 强制使用 Let’s Encrypt

坑2:DNS 验证 TXT 记录添加失败

  • 现象:阿里云 API 返回矛盾日志(既说成功又说失败)
  • 解决--dnssleep 300 给国内 DNS 生效留足缓冲时间

坑3:acme 容器内没有 docker-cli

  • 现象:reloadcmd 执行时报 docker: not found
  • 解决:通过 entrypoint.sh 自动安装 docker-cli,并挂载 docker.sock

坑4:Alpine 容器没有 bash

  • 现象:reloadcmd 用 bashnot found
  • 解决:改用 sh 执行脚本

坑5:Alpine 官方源国内访问慢

  • 现象:apk add 下载超时
  • 解决:换中科大镜像源 mirrors.ustc.edu.cn

坑6:entrypoint 路径写错导致容器不断重启

  • 现象:容器状态 Restarting (127)
  • 解决:用 docker inspect 查看镜像真实入口是 /entry.sh,不是 /usr/local/bin/acme.sh

五、如果从头开始部署带 SSL 的 WordPress

5.1 准备工作

  1. 域名:提前解析到服务器 IP
  2. 阿里云
    • 安全组放行 80 和 443 端口
    • 创建 RAM 子账号,授予 AliyunDNSFullAccess 权限,获取 AccessKey/Secret

5.2 一键部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. 创建目录
mkdir -p ~/wordpress && cd ~/wordpress

# 2. 创建 docker-compose.yml(包含 acme 服务)
# 3. 创建 nginx.conf(直接写 443 配置)
# 4. 创建 entrypoint.sh
# 5. 创建 reload_nginx.sh

# 6. 启动所有服务
docker compose up -d

# 7. 申请证书(一步到位)
docker exec wp-acme acme.sh --set-default-ca --server letsencrypt
docker exec wp-acme acme.sh --register-account -m [email protected]
docker exec wp-acme acme.sh --issue --dns dns_ali \
-d vid.szzhuoju.com \
--dnssleep 300 \
--server letsencrypt \
--force

# 8. 安装证书
docker exec wp-acme acme.sh --install-cert -d vid.szzhuoju.com \
--key-file /acme.sh/certs_out/vid.szzhuoju.com.key \
--fullchain-file /acme.sh/certs_out/vid.szzhuoju.com.pem \
--reloadcmd "sh /root/reload_nginx.sh"

5.3 对比:从零部署 vs 从 HTTP 升级

步骤 从零部署 HTTPS 从 HTTP 升级
nginx.conf 直接写 443 配置 需要从 80 改成 443
证书申请 启动后立即申请 启动后立即申请
WordPress 配置 安装时直接配 HTTPS 需要修改 siteurl 和 home
用户体验 全程无感 可能需要处理混合内容问题

5.4 WordPress 后台配置

如果是从 HTTP 升级过来的,还需要在 WordPress 后台修改站点地址:

1
2
3
4
5
6
# 方法一:通过 wp-cli
docker exec wp-course wp option update siteurl 'https://vid.szzhuoju.com'
docker exec wp-course wp option update home 'https://vid.szzhuoju.com'

# 方法二:直接修改数据库(不推荐)
# 方法三:在 wp-config.php 中强制定义

或者在 wp-config.php 中添加:

1
2
define('WP_HOME', 'https://vid.szzhuoju.com');
define('WP_SITEURL', 'https://vid.szzhuoju.com');

六、自动续期机制

1
2
3
4
5
6
7
8
9
10
acme.sh cron(每天检查4次)
↓ 检测到证书即将过期(<30天)

通过阿里云 DNS API 自动续签

新证书写入 ./cert 目录

执行 reload_nginx.sh

Nginx 热加载新证书(零停机)

整个过程完全自动化,无需人工干预。


七、维护命令速查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看证书到期时间
docker exec wp-acme openssl x509 -enddate -noout -in /acme.sh/certs_out/vid.szzhuoju.com.pem

# 手动续期
docker exec wp-acme acme.sh --cron --force

# 重载 Nginx
docker exec wp-nginx nginx -s reload

# 查看 acme 日志
docker exec wp-acme acme.sh --cron --debug

# 重启所有服务
docker compose down && docker compose up -d

# 单独重启 acme
docker compose down acme && docker compose up -d acme

八、注意事项

  1. 阿里云 RAM 权限:AccessKey 必须有 AliyunDNSFullAccess,否则续期会失败
  2. 安全组:确保 443 端口已放行
  3. 域名解析:域名必须已解析到服务器 IP
  4. 证书有效期:Let’s Encrypt 证书有效期 90 天,自动续期会在到期前 30 天触发
  5. 速率限制:同一域名每周最多申请 5 次证书,不要频繁 --force

    Comments

    回到顶部